package com.ubi.core.framework;

import com.ubi.core.framework.exceptionhandler.GlobalExceptionHandler;
import com.ubi.core.framework.request.RequestContext;
import com.ubi.core.framework.request.RequestContextInterceptor;
import com.ubi.core.framework.response.ErrorResponseBuilder;
import com.ubi.core.json.ObjectMapperCreator;
import com.ubi.core.log.LogExceptionHandler;
import com.ubi.core.log.TrackRequestProcessInterceptor;
import com.ubi.core.monitor.MonitorControllerConfig;
import org.apache.commons.lang3.CharEncoding;
import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.Scope;
import org.springframework.context.annotation.ScopedProxyMode;
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.validation.Validator;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

import java.util.ArrayList;
import java.util.List;

@EnableWebMvc
@Import(MonitorControllerConfig.class)
public class DefaultWebConfig extends WebMvcConfigurerAdapter {

    @Override
    public final void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(requestContextInterceptor());
        registry.addInterceptor(trackRequestProcessInterceptor());
        // registry.addInterceptor(saasContextInterceptor());
        addCustomInterceptors(registry);
        super.addInterceptors(registry);
    }

    public void addCustomInterceptors(InterceptorRegistry registry) {
    }

    @Bean
    public MessageSource messageSource() {
        ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
        messageSource.setBasenames("classpath:messages/common_messages", "classpath:messages/messages");
        messageSource.setDefaultEncoding(CharEncoding.UTF_8);
        return messageSource;
    }

    @Override
    public Validator getValidator() {
        LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
        validator.setValidationMessageSource(messageSource());
        validator.afterPropertiesSet();
        return validator;
    }

    @Override
    public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
        configurer.favorPathExtension(false).favorParameter(true).parameterName("mediaType").ignoreAcceptHeader(true)
            .useJaf(false).defaultContentType(MediaType.APPLICATION_JSON).mediaType("xml", MediaType.APPLICATION_XML)
            .mediaType("json", MediaType.APPLICATION_JSON);
    }

    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        converters.addAll(messageConverters());
    }

    public List<HttpMessageConverter<?>> messageConverters() {
        List<HttpMessageConverter<?>> messageConverters = new ArrayList<>();

        MappingJackson2HttpMessageConverter jsonConverter = new MappingJackson2HttpMessageConverter();
        jsonConverter.setObjectMapper(ObjectMapperCreator.createDefaultObjectMapper());
        messageConverters.add(jsonConverter);

        return messageConverters;
    }

    @Bean
    public ErrorResponseBuilder errorResponseBuilder() {
        return new ErrorResponseBuilder();
    }

    @Bean
    public GlobalExceptionHandler globalExceptionHandler() {
        return new GlobalExceptionHandler();
    }

    @Bean
    public LogExceptionHandler logExceptionHandler() {
        return new LogExceptionHandler();
    }

    @Bean
    @Scope(value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)
    public RequestContext requestContext() {
        return new RequestContext();
    }

    @Bean
    public RequestContextInterceptor requestContextInterceptor() {
        return new RequestContextInterceptor();
    }

    @Bean
    public TrackRequestProcessInterceptor trackRequestProcessInterceptor() {
        return new TrackRequestProcessInterceptor();
    }
}
